#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>

// 函数声明
void aes_encrypt(const unsigned char *plaintext, int plaintext_len, const unsigned char *key, const unsigned char *iv, unsigned char *ciphertext, int *ciphertext_len);
void aes_decrypt(const unsigned char *ciphertext, int ciphertext_len, const unsigned char *key, const unsigned char *iv, unsigned char *plaintext, int *plaintext_len);

int main() {
    // 原始明文和密钥
    const unsigned char *plaintext = (unsigned char *)"Hello, AES!";
    const unsigned char *key = (unsigned char *)"0123456789abcdef";
    const unsigned char *iv = (unsigned char *)"0123456789abcdef"; // 初始化向量IV

    // 加密后的密文和解密后的明文
    unsigned char ciphertext[128];
    unsigned char decryptedtext[128];
    int ciphertext_len, decryptedtext_len;

    // 加密
    aes_encrypt(plaintext, strlen((char *)plaintext), key, iv, ciphertext, &ciphertext_len);

    printf("Ciphertext is:\n");
    for (int i = 0; i < ciphertext_len; i++) {
        printf("%02x ", ciphertext[i]);
    }
    printf("\n");

    // 解密
    aes_decrypt(ciphertext, ciphertext_len, key, iv, decryptedtext, &decryptedtext_len);

    printf("Decrypted text is: %s\n", decryptedtext);

    return 0;
}

// AES加密函数
void aes_encrypt(const unsigned char *plaintext, int plaintext_len, const unsigned char *key, const unsigned char *iv, unsigned char *ciphertext, int *ciphertext_len) {
    EVP_CIPHER_CTX *ctx;

    // 创建并初始化加密上下文
    if (!(ctx = EVP_CIPHER_CTX_new())) {
        fprintf(stderr, "EVP_CIPHER_CTX_new failed.\n");
        exit(1);
    }

    // 初始化加密操作，选择AES-128-CBC模式
    if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv)) {
        fprintf(stderr, "EVP_EncryptInit_ex failed.\n");
        exit(1);
    }

    // 执行加密操作
    if (1 != EVP_EncryptUpdate(ctx, ciphertext, ciphertext_len, plaintext, plaintext_len)) {
        fprintf(stderr, "EVP_EncryptUpdate failed.\n");
        exit(1);
    }

    // 结束加密操作
    int len;
    if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + *ciphertext_len, &len)) {
        fprintf(stderr, "EVP_EncryptFinal_ex failed.\n");
        exit(1);
    }
    *ciphertext_len += len;

    // 清理加密上下文
    EVP_CIPHER_CTX_free(ctx);
}

// AES解密函数
void aes_decrypt(const unsigned char *ciphertext, int ciphertext_len, const unsigned char *key, const unsigned char *iv, unsigned char *plaintext, int *plaintext_len) {
    EVP_CIPHER_CTX *ctx;

    // 创建并初始化解密上下文
    if (!(ctx = EVP_CIPHER_CTX_new())) {
        fprintf(stderr, "EVP_CIPHER_CTX_new failed.\n");
        exit(1);
    }

    // 初始化解密操作，选择AES-128-CBC模式
    if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv)) {
        fprintf(stderr, "EVP_DecryptInit_ex failed.\n");
        exit(1);
    }

    // 执行解密操作
    if (1 != EVP_DecryptUpdate(ctx, plaintext, plaintext_len, ciphertext, ciphertext_len)) {
        fprintf(stderr, "EVP_DecryptUpdate failed.\n");
        exit(1);
    }

    // 结束解密操作
    int len;
    if (1 != EVP_DecryptFinal_ex(ctx, plaintext + *plaintext_len, &len)) {
        fprintf(stderr, "EVP_DecryptFinal_ex failed.\n");
        exit(1);
    }
    *plaintext_len += len;

    // 清理解密上下文
    EVP_CIPHER_CTX_free(ctx);
}
